package thread.wang_bao_ling.c24;

import org.junit.Test;

import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

/**
 * @Auther: luobiao
 * @Date: 2020/7/20 22:48
 * @Description:
 */
public class CompletionStageTest {
    /**
     * 描述串行关系
     */
    @Test
    public  void test1() {
        CompletableFuture<String> f0 =
                CompletableFuture.supplyAsync(
                        () -> "Hello World")
                        .thenApply(s -> s + " QQ")
                        .thenApply(String::toUpperCase);

        System.out.println(f0.join());
    }

    /**
     * 描述AND汇聚关系
     */
    @Test
    public  void test2() {
        CompletableFuture<Integer> f1 =
                CompletableFuture.supplyAsync(()->{
                    int t = getRandomTime("f1");
                    sleep(t, TimeUnit.SECONDS);
                    return t;
                });

        CompletableFuture<Integer> f2 =
                CompletableFuture.supplyAsync(()->{
                    int t = getRandomTime("f2");
                    sleep(t, TimeUnit.SECONDS);
                    return t;
                });

        //f1和f2是and汇聚，要等两个任务都并行执行完成，所以最终执行时间为耗时最长的那个任务时间
        //注意thenCombine第二个参数为BiFunction，因为会等两个任务都并行执行完毕，所以能取到两个任务的执行结果
        CompletableFuture<Integer> f3 =
                f1.thenCombine(f2,(t1,t2) -> {
                    return t1 > t2 ? t1:t2;
                });
        System.out.println("执行时间："+f3.join());
    }

    /**
     * 描述OR汇聚关系
     */
    @Test
    public  void test3() {
        CompletableFuture<Integer> f1 =
                CompletableFuture.supplyAsync(()->{
                    int t = getRandomTime("f1");
                    sleep(t, TimeUnit.SECONDS);
                    return t;
                });

        CompletableFuture<Integer> f2 =
                CompletableFuture.supplyAsync(()->{
                    int t = getRandomTime("f2");
                    sleep(t, TimeUnit.SECONDS);
                    return t;
                });

        //f1和f2是or汇聚，谁先执行就使用谁的结果，所以最终执行时间为耗时最短的那个任务时间
        //注意applyToEither第二个参数为Function，因为只会使用一个任务的返回结果
        CompletableFuture<Integer> f3 =
                f1.applyToEither(f2,s -> s);
        System.out.println("执行时间："+f3.join());
    }

    @Test
    public void test4(){
        CompletableFuture<Integer> f0 = CompletableFuture
                .supplyAsync(() -> (7 / 0))
                .thenApply(r -> r * 10)
                .exceptionally(e -> 0);
        System.out.println(f0.join());
    }

    /**
     * 随机生成休眠的秒数（1-6）
     * @param name
     * @return
     */
    public int getRandomTime(String name){
        Random random = new Random();
        int t=random.nextInt(5)+1;
        System.out.println("t="+t);
        return t;
    }

    void sleep(int t, TimeUnit u) {
        try {
            u.sleep(t);

        } catch (InterruptedException e) {
        }
    }
}
